﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;

namespace Sokoban
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        int height, width;
        int EffectiveHeight, EffectiveWidth;
	//Незначительные изменения для проверки работоспособности репозитория
	bool qwe = false;
        int PlayerX = -1, PlayerY= -1; 
        List<List<int>> Matrix = new List<List<int>>();
        List<Brush> brushes = new List<Brush>();
        List<string> NameOfGamers = new List<string>();
        List<int> PointsOfGamers = new List<int>();
        bool PlayerTarget = false;

        private void FindPlayer()
        {
            for (int i = 0; i < height; i++)
                for (int j = 0; j < width; j++)
                    if (Matrix[j][i] == 2 || Matrix[j][i] == 5)
                    {
                        if (Matrix[j][i] == 5) PlayerTarget = true;
                        PlayerX = j;
                        PlayerY = i;
                    }
        }

        private void LoadLevel()
        {
            Matrix.Clear();
            StreamReader sr = new StreamReader("input.txt");
            height = Convert.ToInt32(sr.ReadLine());
            width = Convert.ToInt32(sr.ReadLine());
            EffectiveHeight = 500 / Math.Min(height, width);
            EffectiveWidth = 500 / Math.Min(height, width);
            brushes = MakeBrushes(EffectiveWidth, EffectiveHeight);
            for (int i = 0; i < width; i++)
            {
                Matrix.Add(new List<int>(width));
                string tmp = sr.ReadLine();
                for (int j = 0; j < height; j++)
                {
                    int buf = -1;
                    if (tmp.Substring(0, 1) == "W") buf = 0;
                    if (tmp.Substring(0, 1) == " ") buf = 1;
                    if (tmp.Substring(0, 1) == "P") buf = 2;
                    if (tmp.Substring(0, 1) == "B") buf = 3;
                    if (tmp.Substring(0, 1) == "T") buf = 4;
                    if (tmp.Substring(0, 1) == "M") buf = 5;
                    if (tmp.Substring(0, 1) == "N") buf = 6;
                    tmp = tmp.Remove(0, 1);
                    Matrix[i].Add(buf);
                }
            }
            FindPlayer();
            Invalidate();
        }

        private List<Brush> MakeBrushes(int ew, int eh)
        {
           Size s = new Size(ew, eh);
           Bitmap BrickTextureUnresized = new Bitmap("brick.jpg");
           Bitmap BrickTexture = new Bitmap(BrickTextureUnresized, s);
           Bitmap ParketTextureUnresized = new Bitmap("parket.jpg");
           Bitmap ParketTexture = new Bitmap(ParketTextureUnresized, s);
           Bitmap BoxTextureUnresized = new Bitmap("box.jpg");
           Bitmap BoxTexture = new Bitmap(BoxTextureUnresized, s);
           Bitmap TargetTextureUnresized = new Bitmap("target.jpg");
           Bitmap TargetTexture = new Bitmap(TargetTextureUnresized, s);
           Bitmap TargetPlayerTextureUnresized = new Bitmap("targetplayer.jpg");
           Bitmap TargetPlayerTexture = new Bitmap(TargetPlayerTextureUnresized, s);
           Bitmap FloorPlayerTextureUnresized = new Bitmap("floorplayer.jpg");
           Bitmap FloorPlayerTexture = new Bitmap(FloorPlayerTextureUnresized, s);
           TextureBrush Brick = new TextureBrush(BrickTexture);
           TextureBrush Parket = new TextureBrush(ParketTexture);
           TextureBrush Box = new TextureBrush(BoxTexture);
           TextureBrush Target = new TextureBrush(TargetTexture);
           TextureBrush TargetPlayer = new TextureBrush(TargetPlayerTexture);
           TextureBrush FloorPlayer = new TextureBrush(FloorPlayerTexture);
           Brush lines = Brushes.Black;
           List<Brush> trash = new List<Brush>();
           trash.Add(Brick);
           trash.Add(Parket);
           trash.Add(FloorPlayer);
           trash.Add(Box);
           trash.Add(Target);
           trash.Add(TargetPlayer);
           trash.Add(Box);
           trash.Add(lines);
           return trash;
        }
        
        private void Form1_Load(object sender, EventArgs e)
        {
            FindAndSortRecords();
            //LoadLevel();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            g.DrawLine(Pens.Black, new Point(500, 0), new Point(500, 500));
            for (int i = 0; i < height; i++)
                for (int j = 0; j < width; j++)
                {
                    g.FillRectangle(brushes[Matrix[j][i]], i * EffectiveWidth, j * EffectiveHeight, EffectiveWidth, EffectiveHeight);
                }
        }


        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Up) ReplacePlayer(-1, 0, 0);
            if (e.KeyCode == Keys.Left) ReplacePlayer(0, -1, 0);
            if (e.KeyCode == Keys.Down) ReplacePlayer(1, 0, height - 1);
            if (e.KeyCode == Keys.Right) ReplacePlayer(0, 1, width - 1);
        }

        private bool CheckGame()
        {
            for (int i = 0; i < height; i++)
                for (int j = 0; j < width; j++)
                    if (Matrix[j][i] == 3)
                        return false;
            MessageBox.Show("Уровень пройден!");
            LoadLevel();
            return true;
        }

        private void ReplacePlayer(int x, int y, int limit)
        {
            if (x != 0)
            {
                if (PlayerX == limit || (PlayerX == limit - x && (Matrix[limit][PlayerY] != 1 && Matrix[limit][PlayerY] != 4))) return;
            }
            if (y != 0)
            {
                if (PlayerY == limit || (PlayerY == limit - y && (Matrix[PlayerX][limit] != 1 && Matrix[PlayerX][limit] != 4))) return;
            }
            if (Matrix[PlayerX + x][PlayerY + y] == 1)
            {
                if (!PlayerTarget) Matrix[PlayerX][PlayerY] = 1;
                else Matrix[PlayerX][PlayerY] = 4;
                PlayerX += x;
                PlayerY += y;
                Matrix[PlayerX][PlayerY] = 2;
                PlayerTarget = false;
                Invalidate();
                CheckGame();
                return;
            }
            if (Matrix[PlayerX + x][PlayerY + y] == 4)
            {
                if (!PlayerTarget) Matrix[PlayerX][PlayerY] = 1;
                else Matrix[PlayerX][PlayerY] = 4;
                PlayerX += x;
                PlayerY += y;
                Matrix[PlayerX][PlayerY] = 5;
                PlayerTarget = true;
                Invalidate();
                CheckGame();
                return;
            }
            if (Matrix[PlayerX + x][PlayerY + y] == 3 && (Matrix[PlayerX + 2 * x][PlayerY + 2 * y] == 1 || Matrix[PlayerX + 2 * x][PlayerY + 2 * y] == 4))
            {
                if (!PlayerTarget) Matrix[PlayerX][PlayerY] = 1;
                else Matrix[PlayerX][PlayerY] = 4;
                Matrix[PlayerX + x][PlayerY + y] = 2;
                if (Matrix[PlayerX + 2 * x][PlayerY + 2 * y] == 1) Matrix[PlayerX + 2 * x][PlayerY + 2 * y] = 3;
                if (Matrix[PlayerX + 2 * x][PlayerY + 2 * y] == 4) Matrix[PlayerX + 2 * x][PlayerY + 2 * y] = 6;
                PlayerTarget = false;
                PlayerX += x;
                PlayerY += y;
                Invalidate();
                CheckGame();
                return;
            }
            if (Matrix[PlayerX + x][PlayerY + y] == 6 && (Matrix[PlayerX + 2 * x][PlayerY + 2 * y] == 1 || Matrix[PlayerX + 2 * x][PlayerY + 2 * y] == 4))
            {
                if (!PlayerTarget) Matrix[PlayerX][PlayerY] = 1;
                else Matrix[PlayerX][PlayerY] = 4;
                Matrix[PlayerX + x][PlayerY + y] = 5;
                if (Matrix[PlayerX + 2 * x][PlayerY + 2 * y] == 1) Matrix[PlayerX + 2 * x][PlayerY + 2 * y] = 3;
                if (Matrix[PlayerX + 2 * x][PlayerY + 2 * y] == 4) Matrix[PlayerX + 2 * x][PlayerY + 2 * y] = 6;
                PlayerTarget = true;
                PlayerX += x;
                PlayerY += y;
                Invalidate();
                CheckGame();
                return;
            }
            return;
        }

        private void FindAndSortRecords()
        {
            StreamReader sr = new StreamReader("records.txt");
            string line;
            while ((line = sr.ReadLine()) != null)
            {
                int k = -1;
                k = line.IndexOf('.');
                line = line.Remove(0, k + 2);
                k = line.IndexOf(' ');
                NameOfGamers.Add(line.Substring(0, k));
                line = line.Remove(0, k + 1);
                PointsOfGamers.Add(Convert.ToInt32(line.Substring(0, line.Length)));
            }

        }
    }
}
